<script setup lang="ts">
import {computed, onMounted, reactive, ref} from 'vue'
import api from '@/api'

import { getCurrentInstance } from 'vue';


interface Props {
  uuid: string
  class?: string
  unset?: boolean
  error?: string
  success?: string
  modelValue?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  uuid: '',
  class: '',
  unset: false,
  error: '未点中正确区域，请重试！',
  success: '验证成功！',
  modelValue: false,
})

const state: {
  loading: boolean
  xy: string[]
  tip: string
  captcha: {
    id: string
    text: string
    base64: string
    width: number
    height: number
  }
} = reactive({
  loading: true,
  xy: [],
  tip: '',
  captcha: {
    id: '',
    text: '',
    base64: '',
    width: 350,
    height: 200,
  },
})

// const emits = defineEmits<{
//   (e: 'destroy'): void
// }>()

const load = async () => {
  state.loading = true
  await api.common.getCaptchaData(props.uuid).then((res:ApiResponse) => {
    state.xy = []
    state.tip = ''
    state.loading = false
    state.captcha = res.data
  })
  console.log(state)
}

const onRecord = (event: MouseEvent) => {
  if (state.xy.length < state.captcha.text.length) {
    state.xy.push(event.offsetX + ',' + event.offsetY)
    if (state.xy.length == state.captcha.text.length) {
      const captchaInfo = [state.xy.join('-'), (event.target as HTMLImageElement).width, (event.target as HTMLImageElement).height].join(';')
      api.common.checkClickCaptcha(props.uuid, captchaInfo, props.unset)
          .then(() => {
            state.tip = props.success
            setTimeout(() => {
              onCallback(captchaInfo)
              onClose()
            }, 1500)
          })
          .catch(() => {
            state.tip = props.error
            setTimeout(() => {
              load()
            }, 1500)
          })
    }
  }
}

const onCancelRecord = (index: number) => {
  state.xy.splice(index, 1)
}

const onClose = () => {
  emit('update:modelValue', false);
}
const emit = defineEmits(['update:modelValue','callback'])

const captchaBoxTop = computed(() => (state.captcha.height + 200) / 2 + 'px')
const captchaBoxLeft = computed(() => (state.captcha.width + 24) / 2 + 'px')

const onCallback = (captchaInfo: string) => {
  emit('callback', {captchaInfo});
}
onMounted(()=>{
  load()
})
const isMp = process.env.UNI_PLATFORM === 'mp-weixin'
const instance = getCurrentInstance();
const onRecordmp = (e) => {
  let x = 0
  let y = 0
  const query = uni.createSelectorQuery().in(instance.proxy);
  query
      .select(".captcha-img")
      .boundingClientRect((data) => {
        x = e.detail.x - data.left
        y = e.detail.y - data.top
        if (state.xy.length < state.captcha.text.length) {
          state.xy.push(x + ',' + y)
          if (state.xy.length == state.captcha.text.length) {
            const captchaInfo = [state.xy.join('-'), data.width, data.height].join(';')
            api.common.checkClickCaptcha(props.uuid, captchaInfo, props.unset)
                .then(() => {
                  state.tip = props.success
                  setTimeout(() => {
                    onCallback(captchaInfo)
                    onClose()
                  }, 1500)
                })
                .catch(() => {
                  state.tip = props.error
                  setTimeout(() => {
                    load()
                  }, 1500)
                })
          }
        }
      })
      .exec();
}
</script>

<template>
    <div :id="uuid">
        <div class="ba-click-captcha" :class="props.class"
             :style="{
              left: `calc(50% - ${captchaBoxLeft})`,
              top: `calc(50% - ${captchaBoxTop})`,
            }"
        >
            <div v-if="state.loading" class="loading">加载中...</div>
            <div v-else class="captcha-img-box">

              <view  v-if="isMp">
                <img class="captcha-img"
                    @tap="onRecordmp"
                     :style="{
                        width: state.captcha.width + 'px',
                        height: state.captcha.height + 'px'
                      }"
                     :src="state.captcha.base64"
                     alt="验证码加载失败，请点击刷新按钮"
                />
              </view>
              <view  v-else>
                <img class="captcha-img"
                     @click.prevent="onRecord($event)"
                     :style="{
                        width: state.captcha.width + 'px',
                        height: state.captcha.height + 'px'
                      }"
                     :src="state.captcha.base64"
                     alt="验证码加载失败，请点击刷新按钮"
                />
              </view>

                <span
                    v-for="(item, index) in state.xy"
                    :key="index"
                    class="step"
                    @click="onCancelRecord(index)"
                    :style="`left:${parseFloat(item.split(',')[0]) - 13}px;top:${parseFloat(item.split(',')[1]) - 13}px`"
                >
                    {{ index + 1 }}
                </span>
            </div>
            <div class="captcha-prompt" v-if="state.tip">
                {{ state.tip }}
            </div>
            <div v-else class="captcha-prompt">
                请依次点击
                <span v-for="(text, index) in state.captcha.text" :key="index" :class="state.xy.length > index ? 'clicaptcha-clicked' : ''">
                    {{ text }}
                </span>
            </div>
            <div class="captcha-refresh-box">
                <div class="captcha-refresh-line captcha-refresh-line-l"></div>
                <uni-icons class="captcha-refresh-btn" type="loop" size="30" title="刷新" @click="load" ></uni-icons>
                <div class="captcha-refresh-line captcha-refresh-line-r"></div>
            </div>
        </div>
        <div class="sm-layout-shade" @click="onClose"></div>
    </div>
</template>

<style scoped lang="scss">
.ba-click-captcha {
    padding: 12px;
    border: 1px solid #f2f6fc;
    background-color: #ffffff;
    position: fixed;
    z-index: 9999991;
    //left: calc(50% - v-bind('captchaBoxLeft'));
    //top: calc(50% - v-bind('captchaBoxTop'));
    border-radius: 10px;
    box-shadow:
        0 0 0 1px hsla(0, 0%, 100%, 0.3) inset,
        0 0.5em 1em rgba(0, 0, 0, 0.6);
    .loading {
        color: #909399;
        width: 350px;
        text-align: center;
        line-height: 200px;
    }
    .captcha-img-box {
        position: relative;
        .captcha-img {
            //width: v-bind('state.captcha.width') px;
            //height: v-bind('state.captcha.height') px;
            border: none;
            cursor: pointer;
        }
        .step {
            box-sizing: border-box;
            position: absolute;
            width: 20px;
            height: 20px;
            line-height: 20px;
            font-size: 13px;
            font-weight: bold;
            text-align: center;
            color: #ffffff;
            border: 1px solid #f2f6fc;
            background-color: #409eff;
            border-radius: 30px;
            box-shadow: 0 0 10px #ffffff;
            user-select: none;
            cursor: pointer;
        }
    }
    .captcha-prompt {
        height: 40px;
        line-height: 40px;
        font-size: 14px;
        text-align: center;
        color: #909399;
        span {
            margin-left: 10px;
            font-size: 16px;
            font-weight: bold;
            color: #f56c6c;
            &.clicaptcha-clicked {
                color: #409eff;
            }
        }
    }
    .captcha-refresh-box {
        position: relative;
        margin-top: 10px;
        .captcha-refresh-line {
            position: absolute;
            top: 16px;
            width: 140px;
            height: 1px;
            background-color: #ccc;
        }
        .captcha-refresh-line-l {
            left: 5px;
        }
        .captcha-refresh-line-r {
            right: 5px;
        }
        .captcha-refresh-btn {
            cursor: pointer;
            display: block;
            margin: 0 auto;
            width: 32px;
            height: 32px;
            font-size: 32px;
            color: #909399 !important;
        }
    }
}
</style>
